<html>
<head><meta charset="utf-8"><title>Naming existential types · wg-async-foundations · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/index.html">wg-async-foundations</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html">Naming existential types</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="245771670"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/245771670" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ibraheem Ahmed <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#245771670">(Jul 13 2021 at 02:04)</a>:</h4>
<p>I didn't see an open issue about this anywhere, so I thought I'd bring it up.</p>
<p>If I want to store a tokio timer in my struct, it's very simple due to tokio's provided concrete future type:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">use</span><span class="w"> </span><span class="n">tokio</span>::<span class="n">time</span>::<span class="n">Sleep</span><span class="p">;</span><span class="w"></span>

<span class="k">struct</span> <span class="nc">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">timer</span>: <span class="nc">Sleep</span><span class="p">,</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>If I want to store an async-std timer in my struct, it get's a little more complicated. Async-std does <em>not</em> provide a concrete timer type, it instead provides an <code>async fn</code>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">pub</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">sleep</span><span class="p">(</span><span class="n">dur</span>: <span class="nc">Duration</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>Which means to store it in my struct, I can either:</p>
<ul>
<li>Make my struct generic over <code>Timer</code> and provide a <code>MyStruct&lt;impl Future&gt;</code>:</li>
</ul>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">Foo</span><span class="o">&lt;</span><span class="n">Timer</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">timer</span>: <span class="nc">Timer</span><span class="p">,</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">create_foo</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Foo</span><span class="o">&lt;</span><span class="k">impl</span><span class="w"> </span><span class="n">Future</span><span class="o">&lt;</span><span class="n">Output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">timer</span>: <span class="nc">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>This doesn't really solve the problem because users of <code>Foo</code> no longer have a concrete type for <em>them</em> to store.</p>
<ul>
<li><code>Box::pin</code></li>
</ul>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">timer</span>: <span class="nc">BoxFuture</span><span class="o">&lt;'</span><span class="nb">static</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">new</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">timer</span>: <span class="nb">Box</span>::<span class="n">pin</span><span class="p">(</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)),</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>This is not an option in <code>no_std</code> environments, and <em>feels</em> pretty unecessary.</p>
<p>On nightly, I can was expecting to be able to write something like:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#![feature(min_tait)]</span><span class="w"></span>

<span class="k">type</span> <span class="nc">TimerFut</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">impl</span><span class="w"> </span><span class="n">Future</span><span class="o">&lt;</span><span class="n">Output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="o">&gt;</span><span class="p">;</span><span class="w"></span>
<span class="k">fn</span> <span class="nf">__defining_use</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">TimerFut</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">async_std</span>::<span class="n">time</span>::<span class="n">sleep</span><span class="p">()</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>But it turns out that doesn't work due to semver concerns. What <em>does</em> work is a wrapper function:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">type</span> <span class="nc">TimerFut</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">impl</span><span class="w"> </span><span class="n">Future</span><span class="o">&lt;</span><span class="n">Output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="o">&gt;</span><span class="p">;</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">sleep</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">TimerFut</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">async_std</span>::<span class="n">time</span>::<span class="n">sleep</span><span class="p">()</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>So when tait stabilizes, will the story change from "you have to box" to "most libraries provide type aliases, and if they don't, create a wrapper function"? There's been discussion of a <code>typeof</code> operator in the past, but I think that would have the same semver implications....</p>



<a name="245771700"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/245771700" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ibraheem Ahmed <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#245771700">(Jul 13 2021 at 02:04)</a>:</h4>
<p>Maybe this is worth a status quo story.</p>



<a name="245771868"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/245771868" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ibraheem Ahmed <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#245771868">(Jul 13 2021 at 02:07)</a>:</h4>
<p>I also think this is somewhat in conflict with the idea of dropping .await.</p>



<a name="245771954"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/245771954" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ibraheem Ahmed <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#245771954">(Jul 13 2021 at 02:08)</a>:</h4>
<p>Making async feel more like sync code also means it's harder to do something like "store a vector of X future in a struct and poll them concurrently"</p>



<a name="245773748"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/245773748" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Zoey <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#245773748">(Jul 13 2021 at 02:46)</a>:</h4>
<p><span class="user-mention silent" data-user-id="363998">Ibraheem Ahmed</span> <a href="#narrow/stream/187312-wg-async-foundations/topic/Naming.20existential.20types/near/245771954">said</a>:</p>
<blockquote>
<p>Making async feel more like sync code also means it's harder to do something like "store a vector of X future in a struct and poll them concurrently"</p>
</blockquote>
<p>As someone writing a service with a lot of interlocking futures, this has been a concern for me as well, as many of the benefits of Rust in this sort of service are lost if you make await implicit and remove cancel-by-drop.</p>



<a name="246245523"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246245523" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246245523">(Jul 16 2021 at 16:22)</a>:</h4>
<p><span class="user-mention" data-user-id="363998">@Ibraheem Ahmed</span> Not sure I follow, what are the semver concerns here?</p>



<a name="246245846"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246245846" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246245846">(Jul 16 2021 at 16:25)</a>:</h4>
<p><span class="user-mention" data-user-id="398288">@Zoey</span> <a href="#narrow/stream/187312-wg-async-foundations/topic/Naming.20existential.20types/near/245773748">said</a>:</p>
<blockquote>
<p>As someone writing a service with a lot of interlocking futures, this has been a concern for me as well, as many of the benefits of Rust in this sort of service are lost if you make await implicit and remove cancel-by-drop.</p>
</blockquote>
<p>I would love to see an example of cancel by drop making code significantly easier to write.</p>



<a name="246249935"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246249935" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ibraheem Ahmed <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246249935">(Jul 16 2021 at 16:58)</a>:</h4>
<p><span class="user-mention silent" data-user-id="116883">tmandry</span> <a href="#narrow/stream/187312-wg-async-foundations/topic/Naming.20existential.20types/near/246245523">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="363998">Ibraheem Ahmed</span> Not sure I follow, what are the semver concerns here?</p>
</blockquote>
<p><a href="https://github.com/rust-lang/rust/issues/86793">https://github.com/rust-lang/rust/issues/86793</a></p>



<a name="246249986"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246249986" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ibraheem Ahmed <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246249986">(Jul 16 2021 at 16:59)</a>:</h4>
<p>Changes to the body of the function could break type aliases.</p>



<a name="246269044"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246269044" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Zoey <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246269044">(Jul 16 2021 at 19:38)</a>:</h4>
<p><span class="user-mention" data-user-id="116883">@tmandry</span> <br>
With streams, it makes it almost Haskell-level tolerable if the individual substreams hold resources alive. I want to avoid having to invoke cleanup myself, and dropping a TCP stream to close its connection conceptually matches with dropping a Futures stream to close its sources.</p>



<a name="246273286"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246273286" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246273286">(Jul 16 2021 at 20:18)</a>:</h4>
<p><span class="user-mention" data-user-id="398288">@Zoey</span> Yeah, that's interesting. I would agree that we still want some form of RAII, and tying it to the stream itself is convenient. If we do something like the <code>Async</code> trait though, it would be a supertrait of (cancellable) <code>Future</code>s, meaning you or a library could impl <code>Future</code> in your stream types and use that capability directly, while also using them in APIs which accept <code>Async</code></p>



<a name="246273545"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246273545" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246273545">(Jul 16 2021 at 20:21)</a>:</h4>
<p>(I'm skeptical about how this will work in more complex situations, though, e.g. stream combinators that want to accept <code>Async</code> instead of <code>Future</code>, making your stream no longer impl <code>Future</code>. I think <span class="user-mention" data-user-id="348152">@Dario Nieuwenhuis</span> was saying something about this)</p>



<a name="246273711"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246273711" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246273711">(Jul 16 2021 at 20:23)</a>:</h4>
<p>That looks equivalent to another problem I want solve, though, which is making it possible to write code that can be "parameterized" as thread safe or thread unsafe</p>



<a name="246273729"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/Naming%20existential%20types/near/246273729" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Zoey <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/Naming.20existential.20types.html#246273729">(Jul 16 2021 at 20:23)</a>:</h4>
<p>I'm also a fan of the A.poll_until(B) pattern, and I've made a few drop utilities - namely <a href="https://github.com/microsoft/snocat/blob/6cde0c721bb6c2980b66154972b539b29e25a16f/snocat/src/util/dropkick.rs">Dropkick</a> to help improve or otherwise utilize drop semantics further.<br>
Combining it with Tokio's CancellationToken has been invaluable in that codebase.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>